/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the EternalTech source code.

 The EternalTech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The EternalTech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the EternalTech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// sg_debug.cpp - debug visualization
//


#include "sg_local.h"


/*
 ==================
 
 ==================
*/
static void SG_DrawEntities (const glqVec3 &viewOrigin, const glqMat3 &viewAxis){

	etEntity	*entity;
	glqSphere	viewSphere, viewSphereText;
	glqPlane	viewPlane;
	glqVec3		center;
	const char	*value;
	int			i;

	if (!sg_showEntities->integerValue || sg_maxShowDistance->floatValue <= 0.0f)
		return;

	// Set up the view spheres and plane for culling
	viewSphere.Set(viewOrigin, sg_maxShowDistance->floatValue);
	viewSphereText.Set(viewOrigin, sg_maxShowDistance->floatValue * 0.25f);

	viewPlane.Set(viewAxis[0], viewOrigin.Dot(viewAxis[0]));

	// Draw the entities
	for (i = 0, entity = level.entities; i < level.numEntities; i++, entity++){
		if (!entity->inUse)
			continue;

		if (!viewSphere.IntersectsBounds(entity->absBounds.Mins(), entity->absBounds.Maxs()))
			continue;		// Doesn't intersect the view sphere

		if (viewPlane.BoundsOnSide(entity->absBounds) == PLANESIDE_BACK)
			continue;		// Completely behind the view plane

		// Draw the bounds
		if (!entity->isLinked || (entity->flags & FL_HIDDEN))
			glqRenderer->DebugBox(colorGray, entity->currentOrigin, entity->currentAxis, entity->bounds, false, VIEW_MAIN);
		else {
			if (entity->state.type == ET_LIGHT)
				glqRenderer->DebugBox(colorYellow, entity->currentOrigin, entity->currentAxis, entity->bounds, false, VIEW_MAIN);
			else if (entity->state.type == ET_SPEAKER)
				glqRenderer->DebugBox(colorBlue, entity->currentOrigin, entity->currentAxis, entity->bounds, false, VIEW_MAIN);
			else {
				// TODO: contents

				glqRenderer->DebugBox(colorRed, entity->currentOrigin, entity->currentAxis, entity->bounds, false, VIEW_MAIN);
			}
		}

		// Don't draw any text if not close enough
		if (!viewSphereText.IntersectsBounds(entity->absBounds.Mins(), entity->absBounds.Maxs()))
			continue;

		center = entity->absBounds.GetCenter();

		// Draw the entity name
		glqRenderer->DebugText(colorWhite, true, center, 2.0f, 4.0f, entity->name, false, VIEW_MAIN);

		// Draw the entity number and class name
		glqRenderer->DebugText(colorWhite, true, center - viewAxis[2] * 4.0f, 2.0f, 4.0f, Str_VarArgs("#%i (%s)", entity->state.number, entity->className), false, VIEW_MAIN);

		// Draw the material, sound shader, or model name if available
		if (entity->state.type == ET_LIGHT)
			value = entity->spawnDict.GetString("material");
		else if (entity->state.type == ET_SPEAKER)
			value = entity->spawnDict.GetString("soundShader");
		else
			value = entity->spawnDict.GetString("model");

		if (!value || !value[0])
			continue;

		glqRenderer->DebugText(colorWhite, true, center - viewAxis[2] * 8.0f, 2.0f, 4.0f, value, false, VIEW_MAIN);
	}
}

/*
 ==================
 
 ==================
*/
static void SG_DrawBinds (const glqVec3 &viewOrigin, const glqMat3 &viewAxis){

}

/*
 ==================
 
 ==================
*/
static void SG_DrawPaths (const glqVec3 &viewOrigin, const glqMat3 &viewAxis){

}

/*
 ==================
 
 ==================
*/
static void SG_DrawTargets (const glqVec3 &viewOrigin, const glqMat3 &viewAxis){

}

/*
 ==================
 
 ==================
*/
static void SG_DrawTriggers (const glqVec3 &viewOrigin, const glqMat3 &viewAxis){

}


// ============================================================================


/*
 ==================
 
 ==================
*/
void SG_DrawDebugTools (){

	glqVec3	viewOrigin;
	glqMat3	viewAxis;

	// If the local client is not connected we can't draw anything
	if (!level.localClient)
		return;

	// Get the current view origin and axis
	viewOrigin = level.localClient->GetViewOrigin();
	viewAxis = level.localClient->GetViewAxis();

	// Draw the entities
	SG_DrawEntities(viewOrigin, viewAxis);

	// Draw entities and their bind masters
	SG_DrawBinds(viewOrigin, viewAxis);

	// Draw path entities and their targets
	SG_DrawPaths(viewOrigin, viewAxis);

	// Draw entities and their targets
	SG_DrawTargets(viewOrigin, viewAxis);

	// Draw trigger entities and their targets
	SG_DrawTriggers(viewOrigin, viewAxis);
}